// config/loader.go
package config

import (
	"fmt"
	"sync"

	"github.com/spf13/viper"
)

// 内部全局变量（仅 loader.go 内部使用）
var (
	configInstance *Config   // 配置实例
	once           sync.Once // 单例初始化锁
)

// 加载器选项（可选，支持自定义配置路径、环境等）
type loaderOptions struct {
	configDir string // 配置文件目录（如 "./configs"）
	env       string // 环境标识（如 "dev" "prod"，用于多环境配置）
}

// LoaderOption 配置加载器的可选参数（函数式选项模式）
type LoaderOption func(*loaderOptions)

// WithConfigDir 设置配置文件目录（可选）
func WithConfigDir(dir string) LoaderOption {
	return func(o *loaderOptions) {
		o.configDir = dir
	}
}

// WithEnv 设置环境（可选，用于多环境配置）
func WithEnv(env string) LoaderOption {
	return func(o *loaderOptions) {
		o.env = env
	}
}

// loadConfig 内部函数：实际加载配置（仅在 loader.go 内部调用）
func loadConfig(opts ...LoaderOption) (*Config, error) {

	// 处理默认选项
	options := loaderOptions{
		configDir: "../../configs", // 默认配置目录
		env:       "",              // 默认不指定环境（加载基础配置）
	}
	for _, opt := range opts {
		opt(&options)
	}

	// 初始化 Viper
	v := viper.New()                   // 局部 Viper 实例，避免全局污染
	v.SetConfigName("config")          // 基础配置文件名（不含扩展名）
	v.SetConfigType("yaml")            // 配置文件类型（yaml）
	v.AddConfigPath(options.configDir) // 配置文件目录

	// 步骤1：读取基础配置（如 config.yaml）
	if err := v.ReadInConfig(); err != nil {
		return nil, fmt.Errorf("读取基础配置失败：%w", err)
	}

	// 步骤2：合并环境特定配置（如 config.dev.yaml，可选）
	if options.env != "" {
		v.SetConfigName(fmt.Sprintf("config.%s", options.env)) // 环境配置文件名（如 config.dev.yaml）
		if err := v.MergeInConfig(); err != nil {
			// 环境配置文件不存在时忽略（允许只提供基础配置）
			if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
				return nil, fmt.Errorf("合并环境配置失败：%w", err)
			}
		}
	}

	// 步骤3：绑定环境变量（可选，优先级：环境变量 > 配置文件）
	bindEnv(v)

	// 步骤4：解析配置到结构体
	var cfg Config
	if err := v.Unmarshal(&cfg); err != nil {
		return nil, fmt.Errorf("配置解析失败：%w", err)
	}

	return &cfg, nil
}

// bindEnv 绑定环境变量（可选功能，让环境变量覆盖配置文件）
func bindEnv(v *viper.Viper) {
	// 格式：v.BindEnv("结构体字段路径", "环境变量名")
	v.BindEnv("server.port", "APP_PORT")          // 环境变量 APP_PORT 覆盖 server.port
	v.BindEnv("database.host", "DB_HOST")         // 环境变量 DB_HOST 覆盖 database.host
	v.BindEnv("database.password", "DB_PASSWORD") // 环境变量 DB_PASSWORD 覆盖 database.password
	// 可根据需要添加更多环境变量绑定...
}
